"""
KidsBuddy 1.0 辅助工具函数
提供各种通用功能的辅助函数
"""

import os
import json
import time
import uuid
from datetime import datetime
from pathlib import Path
from typing import Dict, Any, Optional, Union, List


def generate_unique_id(prefix: str = "") -> str:
    """
    生成一个唯一标识符

    Args:
        prefix: 标识符前缀

    Returns:
        带前缀的唯一标识符
    """
    unique_id = str(uuid.uuid4()).replace("-", "")[:12]
    timestamp = int(time.time())
    return f"{prefix}_{timestamp}_{unique_id}" if prefix else f"{timestamp}_{unique_id}"


def timestamp_to_datetime(timestamp: float) -> datetime:
    """
    将Unix时间戳转换为datetime对象

    Args:
        timestamp: Unix时间戳

    Returns:
        对应的datetime对象
    """
    return datetime.fromtimestamp(timestamp)


def format_timestamp(timestamp: float, format_str: str = "%Y-%m-%d %H:%M:%S") -> str:
    """
    将时间戳格式化为字符串

    Args:
        timestamp: Unix时间戳
        format_str: 格式化字符串

    Returns:
        格式化后的时间字符串
    """
    dt = timestamp_to_datetime(timestamp)
    return dt.strftime(format_str)


def ensure_dir_exists(dir_path: Union[str, Path]) -> Path:
    """
    确保目录存在，如不存在则创建

    Args:
        dir_path: 目录路径

    Returns:
        Path对象表示的目录路径
    """
    path = Path(dir_path)
    path.mkdir(parents=True, exist_ok=True)
    return path


def load_json_file(file_path: Union[str, Path], default: Optional[Dict] = None) -> Dict:
    """
    从文件加载JSON数据

    Args:
        file_path: JSON文件路径
        default: 如果文件不存在或加载失败时返回的默认值

    Returns:
        加载的JSON数据
    """
    path = Path(file_path)
    if not path.exists():
        return default if default is not None else {}

    try:
        with open(path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        print(f"加载JSON文件失败 {file_path}: {e}")
        return default if default is not None else {}


def save_json_file(file_path: Union[str, Path], data: Dict, ensure_dir: bool = True) -> bool:
    """
    将数据保存为JSON文件

    Args:
        file_path: 保存路径
        data: 要保存的数据
        ensure_dir: 是否确保目录存在

    Returns:
        是否保存成功
    """
    path = Path(file_path)

    if ensure_dir:
        path.parent.mkdir(parents=True, exist_ok=True)

    try:
        with open(path, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        return True
    except Exception as e:
        print(f"保存JSON文件失败 {file_path}: {e}")
        return False


def calculate_average(values: List[float], ignore_zero: bool = False) -> float:
    """
    计算列表平均值

    Args:
        values: 数值列表
        ignore_zero: 是否忽略零值

    Returns:
        平均值，如果列表为空则返回0
    """
    if not values:
        return 0.0

    if ignore_zero:
        filtered_values = [v for v in values if v != 0]
        return sum(filtered_values) / len(filtered_values) if filtered_values else 0.0

    return sum(values) / len(values)


def clamp_value(value: float, min_val: float, max_val: float) -> float:
    """
    将值限制在指定范围内

    Args:
        value: 输入值
        min_val: 最小值
        max_val: 最大值

    Returns:
        限制在范围内的值
    """
    return max(min_val, min(value, max_val))


def calculate_score_from_range(value: float, optimal_range: tuple,
                               min_score: float = 0.0, max_score: float = 100.0) -> float:
    """
    根据最佳范围计算评分

    Args:
        value: 输入值
        optimal_range: 最佳范围元组 (min, max)
        min_score: 最低分数
        max_score: 最高分数

    Returns:
        根据范围计算的评分
    """
    low, high = optimal_range

    # 值在最佳范围内
    if low <= value <= high:
        return max_score

    # 值低于最佳范围
    if value < low:
        # 计算与最佳范围的相对距离
        distance_ratio = value / low if low != 0 else 0
        return min_score + (max_score - min_score) * distance_ratio

    # 值高于最佳范围
    else:
        # 计算与最佳范围的相对距离
        max_allowed = high * 2  # 允许的最大值为最佳上限的两倍
        if value >= max_allowed:
            return min_score

        distance_ratio = (max_allowed - value) / (max_allowed - high)
        return min_score + (max_score - min_score) * distance_ratio
